﻿/* ######################################## *\
 * ### Copyright (C) 2009 AJ Ravindiran ### *
 * ### HTTP://THEAJ.NET/ <AJ@THEAJ.NET> ### *
\* ######################################## */
using System;

namespace AJRavindiran.Jolt.Utilities.Logging
{
    /// <summary>
    /// Represents a logger. Prints out log types to the console.
    /// </summary>
    public class Logger
    {
        #region Fields
        /// <summary>
        /// The priority of the log. If log level is lower 
        /// than set priority, the log won't be printed.
        /// </summary>
        private LogLevel mLogPriority;
        #endregion

        #region Properties
        public LogLevel LogPriority
        {
            get { return mLogPriority; }
            set
            {
                if (value != mLogPriority)
                {
                    WriteInfo("Minimum Log Level has changed: " + value + ".");
                }
                mLogPriority = value;
            }
        }
        #endregion

        #region Methods
        private void printLog(ref string logLine, LogLevel logLevel, bool ignoreLogLevel)
        {
            lock (this)
            {
                Console.Write("[{0}]: ", DateTime.Now.ToString("yy.mm.dd hh:mm:ss"));

                if (logLevel == LogLevel.Info)
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                else if (logLevel == LogLevel.Clean)
                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                else if (logLevel == LogLevel.Warn)
                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                else if (logLevel == LogLevel.Error)
                    Console.ForegroundColor = ConsoleColor.DarkRed;
                else if (logLevel == LogLevel.Debug)
                    Console.ForegroundColor = ConsoleColor.DarkCyan;
                else
                    Console.ForegroundColor = ConsoleColor.Gray;

                Console.WriteLine(logLine);
                Console.ForegroundColor = ConsoleColor.Gray;
            }
        }

        /// <summary>
        /// Writes a gray debug log to the console.
        /// This is for debugging purposes.
        /// </summary>
        /// <param name="message">The message to print.</param>
        public void WriteDebug(string message)
        {
            printLog(ref message, LogLevel.Debug, false);
        }

        /// <summary>
        /// Writes a gray plain log to the console.
        /// This ingores the log level priority.
        /// </summary>
        /// <param name="message">The message to print.</param>
        public void WritePlain(string message)
        {
            printLog(ref message, LogLevel.Info, true);
        }

        /// <summary>
        /// Writes a gray information log to the console. 
        /// This is used to display information messages to the user.
        /// </summary>
        /// <param name="message">The message to print.</param>
        public void WriteInfo(string message)
        {
            if (mLogPriority <= LogLevel.Info)
                printLog(ref message, LogLevel.Info, false);
        }

        /// <summary>
        /// Writes a green clean log to the console.
        /// This is used to display successful message to the user.
        /// </summary>
        /// <param name="message">The message to print.</param>
        public void WriteClean(string message)
        {
            if (mLogPriority <= LogLevel.Clean)
                printLog(ref message, LogLevel.Clean, false);
        }

        /// <summary>
        /// Writes a yellow warning log to the console.
        /// This is used to display warning messages to the user.
        /// </summary>
        /// <param name="message">The message to print.</param>
        public void WriteWarn(string message)
        {
            if (mLogPriority <= LogLevel.Warn)
                printLog(ref message, LogLevel.Warn, false);
        }

        /// <summary>
        /// Writes a red error log to the console.
        /// This is used to display error messages to the user.
        /// </summary>
        /// <param name="message">The message to print.</param>
        public void WriteError(string message)
        {
            if (mLogPriority <= LogLevel.Error)
                printLog(ref message, LogLevel.Error, false);
            if (JoltEnvironment.BeepEnabled)
                Console.Beep();
        }

        /// <summary>
        /// Writes an red exception error to the console.
        /// This is used to display unhandled exceptions.
        /// </summary>
        public void WriteException(Exception ex)
        {
            if (JoltEnvironment.DebugMode)
                WriteError(ex.Message + "\n" + ex.StackTrace);
            else
                WriteError(ex.Message);

            if (JoltEnvironment.BeepEnabled)
                Console.Beep();
        }

        /// <summary>
        /// Configuration exception error.
        /// </summary>
        /// <param name="message"></param>
        public void WriteConfigurationParseError(string message)
        {
            if (mLogPriority <= LogLevel.Error)
            {
                string sLine = string.Format("Could not parse configuration field '{0}'.", message);
                printLog(ref sLine, LogLevel.Error, false);
            }
        }

        public void WriteBlank()
        {
            Console.WriteLine();
        }
        #endregion
    }

    /// <summary>
    /// The log levels that the console will follow.
    /// </summary>
    public enum LogLevel
    {
        Debug = 0, // Used for server development. Not for releases.
        Info = 1,  // Used to give user Informative data.
        Clean = 2, // Used to give user successful data.
        Warn = 3,  // Reports problems occured that won't be dangerous to the server
        Error = 4  // Reports serious problems that can affect runtime of server.
    }
}
